/*
 * @Description:
 * @Author: Haor
 * @Date: 2022-04-01 16:50:23
 * @LastEditTime: 2022-04-06 22:15:41
 * @LastEditors: Haor
 */

/**
 * 类型检测
 * @param data 检测值
 * @reutn string/number/object...
 */
export const getType = (data): string => {
  return Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
};

/**
 * 是否为json
 * @param {any} data
 * @return {boolean}
 */
export const isJson = (data = null) => {
    try {
        if (typeof data !== 'string') return false
        const jsonObj = JSON.parse(data)
        return !!(jsonObj && ({}).toString.call(jsonObj) === 'object')
    } catch (error) {}
    return false
}

/**
 * 下划线转驼峰
 * @param {string} str
 * @return {string}
 */
export const lineToHump = (str: string): string => {
  return str.toLowerCase().replace(/([a-z])|-([a-z])/g, (s, s1) => {
    return s1.toUpperCase();
  });
};

/**
 * 驼峰转为下划线
 * @param {string} str
 * @return {string}
 */
export const humpToUnderline = (str: string):string => {
    return str.replace(/([A-Z])/g, '_$1').toLowerCase()
}

/**
 * 下滑线转为驼峰
 * @param {string} str
 * @return {string}
 */
export const underlineToCamelCase = (str: string): string => {
    return str.replace(/_(\w)/g, (all, letter) => {
        return letter.toUpperCase()
    })
}

/**
 * 中横线转为驼峰
 * @param {string} str
 * @return {string}
 */
export const middleLineToCamelCase = (str: string): string => {
    return str.replace(/-(\w)/g, (all, letter) => {
        return letter.toUpperCase()
    })
}

/**
 * 转换Key
 * @param obj
 * @param keyMap
 * @param isDeep Boolean 是否深度
 * @return Object/Array
 */
export const convertKey = (
  obj: object,
  keyMap: object,
  isDeep?: boolean,
): object => {
  if (!['array', 'object'].includes(getType(obj))) {
    throw new TypeError(
      'The first argument should be either an object or an array！',
    );
  }
  if ({}.toString.call(keyMap) !== 'object') {
    throw new TypeError('The parameter keyMap should be an object!');
  }
  const res = obj instanceof Array ? [] : {};
  if (obj instanceof Object) {
    for (const key in obj) {
      const newKey = Object.keys(keyMap).includes(key) ? keyMap[key] : key;
      res[newKey] = obj[key];

      //是否为深度转换
      if (
        isDeep &&
        obj[key] instanceof Object &&
        Object.keys(obj[key]).length
      ) {
        res[newKey] = convertKey(obj[key], keyMap, isDeep);
      }
    }
  }
  return res;
};

/**
 * 对象key转为驼峰
 * @param {Object} data
 * @returns {Object}
 */
export const objectKeyCamelCase = (data: object): object => {
  return Object.keys(data).reduce((res, key) => {
    res[underlineToCamelCase(key)] = data[key];
    return res;
  }, {});
};

/**
 * 列表key转为驼峰
 * @param {Array<object>} data
 */
export const listUnderlineKeyToHump = (data: Array<object>): Array<object> => {
    return data.map(row => objectKeyCamelCase(row))
}

/**
 * 列表分组
 * @param {Array} list 列表
 * @param {Function} cb 回调函数，分组所使用字段
 * @return {Array}
 */
export const listGroupBy = (list: Array<any>, cb: Function) => {
  if (!Array.isArray(list)) return {}
  return list.reduce((wrap, cur, idx) => {
      const groupKey = cb ? cb(cur, idx) : null
      if (!groupKey) return wrap
      if (!wrap[groupKey]) {
          wrap[groupKey] = []
      }
      wrap[groupKey].push(cur)
      return wrap
  }, {})
}

/**
 * 分页容器
 * @param {Number} pageIndex
 * @param {Number} pageSize
 * @return {Object}
 */
export const pageWrap = (pageIndex: number | string, pageSize: number | string) => {
    return {
        take: Number(pageSize) || 10,
        skip: (Number(pageIndex) - 1 || 0) * Number(pageSize)
    }
}

/**
 * 是否为数字
 * @param {any} val
 * @return {boolean}
 */
export const isNumber = (val: any): Boolean => {
    if (val === '') return false
    return /^[0-9]*$/.test(val)
}

/**
 * 列表转为tree
 * @param {Array} list 列表
 * @param {Number|String} parentId 父亲id，调用传入根id
 */
export const listToTree = (list, parentId) => {
    let res = []
    if (!Array.isArray(list)) return []
    for (let i = 0, len = list.length; i < len; i++) {
        const menu = list[i]
        if (menu.pid === parentId) {
            res.push(menu)
            const children = listToTree(list, menu.id) // 找出下一级
            menu.children = children.length ? children : null;
        }
    }
    return res;
}

/**
 * 列表转为树，高性能浅拷贝版本
 * @param {Array} data
 * @param rootId
 * @return {*[]}
 */
export const toTree = (data, rootId) => {
    if (!data) return []
    const list = data
    const keyMap = {}
    const res = []
    while (list.length > 0) {
        const item = list.shift();
        if (!keyMap[item.id]) {
            item.children = []
            keyMap[item.id] = item
        }
        // 判断当前是否为根
        if (item.pid === rootId) {
            res.push(keyMap[item.id])
        } else {
            const parent = keyMap[item.pid]; // 找到父级
            if (parent) {
                parent.children = Array.isArray(parent.children) ? parent.children.concat(item) : [item]
            } else {
                list.push(item) // 如果没有找到上级，放在最后执行，等找到上级了再执行
            }
        }
    }
    return res
}

